home *** CD-ROM | disk | FTP | other *** search
/ Aminet 25 / Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso / Aminet / util / pack / xpk_Source.lha / xpk_Source / xpkmaster / xpkmaster.c < prev    next >
C/C++ Source or Header  |  1998-03-26  |  20KB  |  709 lines

  1. #ifndef XPKMASTER_XPKMASTER_C
  2. #define XPKMASTER_XPKMASTER_C
  3.  
  4. /* Routinesheader
  5.  
  6.     Name:        xpkmaster.c
  7.     Main:        xpkmaster
  8.     Versionstring:    $VER: xpkmaster.c 1.13 (21.02.1998)
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    the main xpk functions
  12.  
  13.  1.0   09.10.96 : first real version
  14.  1.1   27.12.96 : removed 1.3 specific functions
  15.  1.2   10.01.97 : corrected XpkPack's abort
  16.  1.3   11.01.97 : corrected mem bug (reported by Laurent Kempe)
  17.  1.4   30.01.97 : hopefully fixed mem bug finally
  18.  1.5   31.01.97 : bug still occured
  19.  1.6   01.03.97 : added NoPack stuff to XpkWrite and XpkPack
  20.  1.7   24.03.97 : fixed XpkPack
  21.  1.8   25.03.97 : added AutoPasswd
  22.  1.9   28.03.97 : moved autopassword into xpkopen
  23.  1.10  01.04.97 : fixed NoPack error
  24.  1.11  19.12.97 : added xfdmaster support, made MBUG defines
  25.  1.12  09.01.98 : better passkey handling
  26.  1.13  21.02.98 : uses new style register definition
  27. */
  28.  
  29. /**************************************************/
  30. #ifdef __MAXON__                /**/
  31.   #define MBUGDEF    ULONG maxon_bug;    /**/
  32.   #define MBUG        maxon_bug = (ULONG)    /**/
  33. #else                        /**/
  34.   #define MBUG                      /**/
  35.   #define MBUGDEF                /**/
  36. #endif                        /**/
  37. /**************************************************/
  38.  
  39. #include <proto/exec.h>
  40. #include <proto/intuition.h>
  41. #include <proto/dos.h>
  42. #include <proto/utility.h>
  43. #include <proto/xpkmaster.h>
  44. #include <proto/xfdmaster.h>
  45. #include <proto/xpksub.h>
  46. #include <exec/types.h>
  47. #include <exec/memory.h>
  48. #include <exec/tasks.h>
  49. #include <dos/dos.h>
  50. #include "xpkmaster.h"
  51. #include "texts.h"
  52.  
  53. #ifdef USE_POWERPACKER
  54.   #include <proto/powerpacker.h>
  55.   #include <libraries/ppbase.h>
  56. #endif
  57.  
  58. #ifdef SUPPORT_A4
  59.   LONG XpkOpenA4NAME(struct XpkFib **xfh, struct TagItem *tags, ULONG a4);
  60.   #ifdef __SASC
  61.     #pragma libcall XpkBase XpkOpenA4NAME 036 C9803
  62.   #else
  63.     #pragma amicall(XpkBase,0x36,XpkOpenA4NAME(a0,a1,a4))
  64.   #endif
  65. #else
  66.   #define XpkOpenA4NAME XpkOpen
  67. #endif
  68.  
  69. /**************************************************************************
  70.  *
  71.  *   XpkPack() - pack a file
  72.  *
  73.  */
  74.  
  75. ASM(LONG) LIBXpkPack(REG(a0, struct TagItem *tags) A4PROTO)
  76. {
  77.   struct XpkBuffer *xbuf = 0;
  78.   STRPTR buf;
  79.   LONG totlen, res, chunklen;
  80.  
  81.   if(!FindTagItem(XPK_PackMethod, tags))
  82.     return XPKERR_BADPARAMS;
  83.  
  84.   if((res = XpkOpenA4NAME((struct XpkFib **) &xbuf, tags A4SUPP)))
  85.     return res;
  86.  
  87.   totlen = xbuf->xb_InLen;
  88.  
  89.   CurrentTime(&xbuf->xb_Secs, &xbuf->xb_Mics); /* Start the clock */
  90.  
  91.   xbuf->xb_Prog.xp_Type = XPKPROG_START;
  92.   xbuf->xb_Prog.xp_ULen = totlen;
  93.   if(callprogress(xbuf))
  94.     return XpkClose((struct XpkFib *) xbuf);
  95.  
  96.   while(totlen > 0)
  97.   {
  98.     chunklen = xbuf->xb_Fib.xf_NLen;
  99.  
  100.     if(!(buf = (STRPTR) hookread(xbuf, XIO_READ, NULL, chunklen)))
  101.       break;
  102.  
  103.     if(XpkWrite((struct XpkFib *) xbuf, buf, chunklen))
  104.       break;
  105.  
  106.     totlen -= chunklen;
  107.  
  108.     xbuf->xb_Prog.xp_Type = XPKPROG_MID;    /* Progress report     */
  109.     xbuf->xb_Prog.xp_UCur += chunklen;
  110.     xbuf->xb_Prog.xp_CCur = xbuf->xb_Fib.xf_CCur;
  111.     if(callprogress(xbuf))
  112.       return XpkClose((struct XpkFib *) xbuf);
  113.   }
  114.  
  115.   if(xbuf->xb_Prog.xp_Type)
  116.   {
  117.     xbuf->xb_Prog.xp_Type = XPKPROG_END;
  118.     xbuf->xb_Prog.xp_CCur += xbuf->xb_Headers.h_LocSize;
  119.     xbuf->xb_Prog.xp_Activity = xbuf->xb_Result ?
  120.       strings[TXT_ABORTED] : xbuf->xb_LastMsg;
  121.     callprogress(xbuf);     /* Call the hook one last time */
  122.   }
  123.  
  124.   return XpkClose((struct XpkFib *) xbuf);
  125. }
  126.  
  127. /*********************************************************************
  128.  *
  129.  * XpkUnpack - unpack a file
  130.  *
  131.  */
  132.  
  133. ASM(LONG) LIBXpkUnpack(REG(a0, struct TagItem *tags) A4PROTO)
  134. {
  135.   struct XpkBuffer *xbuf = NULL;
  136.   STRPTR pointer;
  137.   LONG len, res;
  138.  
  139. #ifdef DEBUG
  140.   DebugRunTime("XpkUnpack");
  141. #endif
  142.  
  143.   if((res = XpkOpenA4NAME((struct XpkFib **) &xbuf, tags A4SUPP)))
  144.     return res;
  145.  
  146.   if(xbuf->xb_Flags & XMF_PACKING)
  147.   {
  148.     xbuf->xb_Result = XPKERR_BADPARAMS;
  149.     goto Abort;
  150.   }
  151.  
  152.   CurrentTime(&xbuf->xb_Secs, &xbuf->xb_Mics); /* Start the clock */
  153.  
  154.   xbuf->xb_Prog.xp_Type = XPKPROG_START;    /* Initialize progress */
  155.   xbuf->xb_Prog.xp_ULen = xbuf->xb_Fib.xf_ULen;
  156.   if(callprogress(xbuf))
  157.     goto Abort;
  158.  
  159.   if(!hookwrite(xbuf, XIO_TOTSIZE, NULL, xbuf->xb_Fib.xf_ULen + XPK_MARGIN))
  160.   {
  161. #ifdef DEBUG
  162.     DebugError("XpkUnpack: XIO_TOTSIZE failed");
  163. #endif
  164.     goto Abort;
  165.   }
  166.  
  167.   if(!(pointer = (STRPTR) hookwrite(xbuf, XIO_GETBUF, 0, xbuf->xb_Fib.xf_NLen)))
  168.   {
  169. #ifdef DEBUG
  170.     DebugError("XpkUnpack: XIO_GETBUF failed (a)");
  171. #endif
  172.     goto Abort;
  173.   }
  174.  
  175. #ifdef DEBUG
  176.   if(xbuf->xb_Result)
  177.     DebugError("XpkUnpack: failure before unpackloop");
  178. #endif
  179.  
  180.   while((len = XpkRead((struct XpkFib *) xbuf, pointer, xbuf->xb_Fib.xf_NLen)) > 0)
  181.   {
  182.     if(!hookwrite(xbuf, XIO_WRITE, pointer, len))
  183.     {
  184. #ifdef DEBUG
  185.       DebugError("XpkUnpack: XIO_WRITE failed");
  186. #endif
  187.       goto Abort;
  188.     }
  189.  
  190.     xbuf->xb_Prog.xp_Type = XPKPROG_MID;    /* Progress report     */
  191.     xbuf->xb_Prog.xp_CCur = xbuf->xb_Fib.xf_CCur;
  192.     xbuf->xb_Prog.xp_UCur = xbuf->xb_Fib.xf_UCur;
  193.     if(callprogress(xbuf))
  194.       goto Abort;
  195.  
  196.     if(!(pointer = (STRPTR) hookwrite(xbuf, XIO_GETBUF, NULL, xbuf->xb_Fib.xf_NLen)))
  197.     {
  198. #ifdef DEBUG
  199.       DebugError("XpkUnpack: XIO_GETBUF failed (b)");
  200. #endif
  201.       goto Abort;
  202.     }
  203.   }
  204.  
  205.   xbuf->xb_Result = len;
  206. #ifdef DEBUG
  207.   if(xbuf->xb_Result)
  208.     DebugError("XpkUnpack: XpkRead failed with %ld", xbuf->xb_Result);
  209. #endif
  210.  
  211.   if(xbuf->xb_Prog.xp_Type)
  212.   {
  213.     xbuf->xb_Prog.xp_Type = XPKPROG_END;
  214.     xbuf->xb_Prog.xp_Activity = xbuf->xb_Result ? strings[TXT_ABORTED] : xbuf->xb_LastMsg;
  215.     callprogress (xbuf);    /* Call the hook one last time */
  216.   }
  217. Abort:
  218.   return XpkClose((struct XpkFib *) xbuf);
  219. }
  220.  
  221. /*********************************************************************
  222.  *
  223.  * XpkOpen - open a file for packing/unpacking
  224.  *
  225.  */
  226.  
  227. ASM(LONG) LIBXpkOpen(REG(a0, struct XpkBuffer **xbufp),
  228.     REG(a1, struct TagItem *tags) A4PROTO)
  229. {
  230. #if defined(DEBUG) && defined(SUPPORT_A4)
  231.   DebugRunTime("XpkOpen: A4 = %ld", a4);
  232. #elif defined(DEBUG)
  233.   DebugRunTime("XpkOpen");
  234. #endif
  235.   return xpkopen(xbufp, tags, 0 A4SUPP);
  236. }
  237.  
  238. /**************************************************************************
  239.  *
  240.  *   XpkExamine() - inspect a compressed file
  241.  *
  242.  */
  243.  
  244. ASM(LONG) LIBXpkExamine(REG(a0, struct XpkFib *fib),
  245.     REG(a1, struct TagItem *tags) A4PROTO)
  246. {
  247.   struct XpkBuffer *dummy;
  248.   LONG res;
  249.  
  250. #if defined(DEBUG) && defined(SUPPORT_A4)
  251.   DebugRunTime("XpkExamine: A4 = %ld", a4);
  252. #elif defined(DEBUG)
  253.   DebugRunTime("XpkExamine");
  254. #endif
  255.  
  256.   if((res = xpkopen(&dummy, tags, 1 A4SUPP)))
  257.     return res;
  258.  
  259.   CopyMem(dummy, fib, sizeof(struct XpkFib));
  260.   /* copies the entries of XpkFib
  261.      *fib = dummy->Fib works too, but calls it's own copy-function */
  262.  
  263.   return XpkClose((struct XpkFib *) dummy);
  264. }
  265.  
  266. /**************************************************************************
  267.  *
  268.  *   XpkRead() - read one chunk from a compressed file
  269.  *
  270.  */
  271.  
  272. ASM(LONG) LIBXpkRead(REG(a0, struct XpkBuffer *xbuf), REG(a1, STRPTR buf),
  273.     REG(d0, ULONG len))
  274. {
  275.   MBUGDEF
  276.  
  277. #ifdef DEBUG
  278.   DebugRunTime("XpkRead: buf %08lx, size %ld", buf, len);
  279. #endif
  280.  
  281.   if(!xbuf)
  282.     return XPKERR_NOFUNC;
  283.  
  284.   if(xbuf->xb_Flags & XMF_EOF)
  285.     return 0;
  286.  
  287.   switch(xbuf->xb_Format) 
  288.   {
  289.     /*********************** Unpack standard XPK *******************/
  290.   case XPKMODE_UPSTD:
  291.     {
  292.       struct XpkSubParams *xpar;
  293.       struct Library *XpkSubBase = xbuf->xb_SubBase;
  294.       XpkChunkHeader *lochdr = &(xbuf->xb_Headers.h_Loc);
  295.       LONG ulen, clen, rclen, lochdrsize = xbuf->xb_Headers.h_LocSize;
  296.       ULONG csum;
  297.  
  298.       if(lochdr->xch_Word.xchw_Type == XPKCHUNK_END)
  299.         return 0;
  300.  
  301.       if((MBUG hchecksum((STRPTR) lochdr, lochdrsize)))
  302.       {
  303. #ifdef DEBUG
  304.         DebugError("XpkRead: hchecksum(,%ld) failed", lochdrsize);
  305. #endif
  306.         return(xbuf->xb_Result = XPKERR_CHECKSUM);
  307.       }
  308.  
  309.       if(xbuf->xb_Headers.h_Glob.xsh_Flags & XPKSTREAMF_LONGHEADERS)
  310.         ulen = lochdr->xch_Long.xchl_ULen, clen = lochdr->xch_Long.xchl_CLen;
  311.       else
  312.         ulen = lochdr->xch_Word.xchw_ULen, clen = lochdr->xch_Word.xchw_CLen;
  313.       rclen = ROUNDLONG(clen);
  314.  
  315.       if(lochdr->xch_Word.xchw_Type == XPKCHUNK_RAW)
  316.       {
  317.         if(!(MBUG hookread(xbuf, XIO_READ, buf, rclen + lochdrsize)))
  318.       return xbuf->xb_Result;
  319.  
  320.         if(!(xbuf->xb_Flags & XMF_NOCRC))
  321.       if((csum=cchecksum((ULONG *) buf, rclen >>2)) != lochdr->xch_Word.xchw_CChk)
  322.       {
  323. #ifdef DEBUG
  324.         DebugError("XpkRead: cchecksum(,%ld) = %lx != %lx failed", rclen >> 2, csum, (ULONG) lochdr->xch_Word.xchw_CChk);
  325. #endif
  326.         return (xbuf->xb_Result = XPKERR_CHECKSUM);
  327.           }
  328.  
  329.         CopyMem(buf + rclen, lochdr, lochdrsize);
  330.       }
  331.       else if(lochdr->xch_Word.xchw_Type == XPKCHUNK_PACKED)
  332.       {
  333.         xpar = &xbuf->xb_PackParam;
  334.         if(!(xpar->xsp_InBuf = hookread(xbuf, XIO_READ, NULL, rclen + lochdrsize)))
  335.       return xbuf->xb_Result;
  336.  
  337.         if(!(xbuf->xb_Flags & XMF_NOCRC))
  338.       if((csum=cchecksum((ULONG *)xpar->xsp_InBuf, rclen >> 2)) != lochdr->xch_Word.xchw_CChk)
  339.       {
  340. #ifdef DEBUG
  341.         DebugError("XpkRead: cchecksum(,%ld) = %lx != %lx failed", rclen >>2 , csum, (ULONG) lochdr->xch_Word.xchw_CChk);
  342. #endif
  343.         return (xbuf->xb_Result = XPKERR_CHECKSUM);
  344.           }
  345.         xbuf->xb_Flags |= XMF_INITED;
  346.  
  347.         xpar->xsp_InLen = clen;
  348.         xpar->xsp_OutLen = ulen;
  349.         xpar->xsp_OutBuf = buf;
  350.         xpar->xsp_OutBufLen = ulen;
  351.         xpar->xsp_Number = 0;
  352.         xpar->xsp_Password = xbuf->xb_Password;
  353.         xpar->xsp_LibVersion = xbuf->xb_Headers.h_Glob.xsh_SubVrs;
  354.  
  355.         if((xbuf->xb_Result = XpksUnpackChunk(xpar)))
  356.       return xbuf->xb_Result;
  357.  
  358.         CopyMem((STRPTR) xpar->xsp_InBuf + rclen, lochdr, lochdrsize);
  359.       }
  360.       else
  361.         return (xbuf->xb_Result = XPKERR_CORRUPTPKD);
  362.  
  363.       updatefib(xbuf);
  364.       return ulen;
  365.     }
  366. #ifdef USE_POWERPACKER
  367.     /********************* Unpack powerpacked file ****************/
  368.   case XPKMODE_UPPP:
  369.     {
  370.       struct Library *PPBase = xbuf->xb_SubBase;
  371.       STRPTR inbuf, inbufend;
  372.  
  373.       if(!(inbuf = (STRPTR) hookread(xbuf, XIO_READ, NULL, xbuf->xb_InLen - 4)))
  374.         return xbuf->xb_Result;
  375.       inbufend = inbuf + xbuf->xb_InLen - 4;
  376.  
  377.       ppDecrunchBuffer(inbufend, buf, (ULONG *) inbuf, DECR_NONE);
  378.  
  379.       xbuf->xb_Fib.xf_CCur = xbuf->xb_InLen;
  380.       xbuf->xb_Fib.xf_UCur = xbuf->xb_Fib.xf_ULen;
  381.       xbuf->xb_Fib.xf_NLen = 0;
  382.       xbuf->xb_Flags |= XMF_EOF;
  383.  
  384.       return (LONG) xbuf->xb_Fib.xf_ULen;
  385.     }
  386. #endif /* USE_POWERPACKER */
  387.  
  388.   /**************************** xfdmaster file **************************/
  389.   case XPKMODE_UPXFD:
  390.     {
  391.       struct xfdMasterBase *xfdMasterBase = (struct xfdMasterBase *) xbuf->xb_SubBase;
  392.       struct xfdBufferInfo *xbi = xbuf->xb_xfd;
  393.  
  394.       xbi->xfdbi_Flags = XFDFF_USERTARGET;
  395.       xbi->xfdbi_UserTargetBuf = buf;
  396.       xbi->xfdbi_UserTargetBufLen = len;
  397.       if((xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY32) &&
  398.       (xbuf->xb_Flags & XMF_KEY32))
  399.         xbi->xfdbi_Special = &xbuf->xb_PassKey32;
  400.       else if((xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY16) &&
  401.       (xbuf->xb_Flags & XMF_KEY16))
  402.         xbi->xfdbi_Special = &xbuf->xb_PassKey16;
  403.       else if(xbuf->xb_Fib.xf_Flags & XPKFLAGS_PASSWORD)
  404.         xbi->xfdbi_Special = xbuf->xb_Password;
  405.  
  406.       if(!xfdDecrunchBuffer(xbi))
  407.       {
  408.         switch(xbi->xfdbi_Error)
  409.         {
  410.         case XFDERR_NOMEMORY: xbuf->xb_Result = XPKERR_NOMEM; break;
  411.         case XFDERR_WRONGPASSWORD: case XFDERR_WRONGKEY:
  412.           xbuf->xb_Result = XPKERR_WRONGPW; break;
  413.         case XFDERR_CORRUPTEDDATA: xbuf->xb_Result = XPKERR_CORRUPTPKD; break;
  414.         case XFDERR_BETTERCPU: xbuf->xb_Result = XPKERR_WRONGCPU; break;
  415.         default: xbuf->xb_Result = XPKERR_UNKNOWN; break;
  416.         }
  417.  
  418. #ifdef DEBUG
  419.   DebugRunTime("XpkRead: xfd failed with %ld", xbuf->xb_Result);
  420. #endif
  421.         return xbuf->xb_Result;
  422.       } /* xfdDecrunchBuffer */
  423.  
  424.       xbuf->xb_Fib.xf_CCur = xbuf->xb_InLen;
  425.       xbuf->xb_Fib.xf_UCur = xbuf->xb_Fib.xf_ULen;
  426.       xbuf->xb_Fib.xf_NLen = 0;
  427.       xbuf->xb_Flags |= XMF_EOF;
  428.  
  429. #ifdef DEBUG
  430.   DebugRunTime("XpkRead: xfd returns %ld", xbuf->xb_Fib.xf_ULen);
  431. #endif
  432.       return (LONG) xbuf->xb_Fib.xf_ULen;
  433.     }
  434.     /********************* Unpack unpacked file *******************/
  435.   case XPKMODE_UPUP:
  436.     {
  437.       ULONG leftlen = xbuf->xb_Fib.xf_ULen - xbuf->xb_Fib.xf_CCur;
  438.  
  439.       if(leftlen > len)
  440.     leftlen = len;
  441.       else
  442.         xbuf->xb_Flags |= XMF_EOF;
  443.  
  444.       if(!(MBUG hookread(xbuf, XIO_READ, buf, leftlen)))
  445.         return xbuf->xb_Result;
  446.  
  447.       xbuf->xb_Fib.xf_CCur += leftlen;
  448.       xbuf->xb_Fib.xf_UCur += leftlen;
  449.       xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen -
  450.         xbuf->xb_Fib.xf_UCur, DEFAULTCHUNKSIZE) + XPK_MARGIN;
  451.  
  452.       return (LONG) leftlen;
  453.     }
  454.   }
  455.  
  456.   return xbuf->xb_Result;
  457. }
  458.  
  459. /**************************************************************************
  460.  *
  461.  *   XpkWrite() - write a chunk to a compressed file
  462.  *
  463.  */
  464.  
  465. ASM(LONG) LIBXpkWrite(REG(a0, struct XpkBuffer *xbuf), REG(a1, STRPTR buf),
  466.     REG(d0, ULONG ulen))
  467. {
  468.   struct Library *XpkSubBase = xbuf->xb_SubBase;
  469.   struct XpkSubParams *xpar;
  470.   struct Headers *head = &xbuf->xb_Headers;
  471.   LONG clen, rclen, outbuflen;
  472.   UWORD end[2] = {0,0}; /* last ULONG of buffer, when not longword bounded */
  473.   UBYTE type;
  474.   STRPTR outbuf;
  475.   MBUGDEF
  476.  
  477.   if(!xbuf->xb_FirstChunk)
  478.     xbuf->xb_FirstChunk = ulen;
  479.   if(ulen > xbuf->xb_FirstChunk)
  480.     return (xbuf->xb_Result = XPKERR_BADPARAMS);
  481.  
  482.   if(xbuf->xb_Flags & XMF_NOPACK) /* no packing */
  483.   {
  484.     hookwrite(xbuf, XIO_WRITE, buf, ulen);
  485.     xbuf->xb_Fib.xf_UCur += ulen;
  486.     xbuf->xb_Fib.xf_CCur += ulen;
  487.     xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
  488.       (LONG) xbuf->xb_ChunkSize);
  489.     return xbuf->xb_Result;
  490.   }
  491.  
  492.   /******************* Write the GlobHdr ********************/
  493.   if(!(xbuf->xb_Flags & XMF_GLOBHDR))
  494.   {
  495.     if(!xbuf->xb_Password)
  496.       CopyMem(buf, head->h_Glob.xsh_Initial, Min(16, ulen));
  497.     xbuf->xb_Flags |= XMF_GLOBHDR;
  498.     if(!(MBUG hookwrite(xbuf, XIO_WRITE, &head->h_Glob,
  499.     sizeof(struct XpkStreamHeader))))
  500.       return xbuf->xb_Result;
  501.     xbuf->xb_Fib.xf_CCur += sizeof(struct XpkStreamHeader);
  502.   }
  503.  
  504.   /******************* Allocate the buffer *****************/
  505.   outbuflen = ROUNDLONG(ulen + (ulen>>5) + head->h_LocSize) + XPK_MARGIN;
  506.   if(!(outbuf = (STRPTR) hookwrite(xbuf, XIO_GETBUF, NULL, outbuflen)))
  507.     return xbuf->xb_Result;
  508.  
  509.   outbuf += head->h_LocSize;
  510.   /* compress to behind local header. This is needed by mem-out hook! */
  511.  
  512.   if(ulen < xbuf->xb_SubInfo->xi_MinPkInChunk)
  513.     goto copychunk;
  514.  
  515.   /******************* Pack the chunk **********************/
  516.   xpar = &xbuf->xb_PackParam;
  517.   xpar->xsp_InBuf = buf;
  518.   xpar->xsp_InLen = ulen;
  519.   xpar->xsp_OutBuf = outbuf;
  520.   xpar->xsp_OutBufLen = outbuflen - head->h_LocSize;
  521.   xpar->xsp_Number += 1;
  522.   xpar->xsp_Mode = xbuf->xb_PackingMode;
  523.   xpar->xsp_Password = xbuf->xb_Password;
  524.   xpar->xsp_LibVersion = xbuf->xb_SubInfo->xi_LibVersion;
  525.  
  526.   xbuf->xb_Result = XpksPackChunk(xpar);
  527.   xbuf->xb_Flags |= XMF_INITED;
  528.  
  529.   type = XPKCHUNK_PACKED;
  530.   clen = xpar->xsp_OutLen;
  531.  
  532.   if(xbuf->xb_Result == XPKERR_EXPANSION)
  533.   {
  534.     xbuf->xb_Result = 0;
  535. copychunk:
  536.     type = XPKCHUNK_RAW;
  537.     clen = ulen;
  538.     outbuf = buf;
  539.   }
  540.  
  541.   if(xbuf->xb_Result)
  542.     return xbuf->xb_Result;
  543.  
  544.   /******************* Write the chunk **********************/
  545.   head->h_Loc.xch_Word.xchw_Type = type;
  546.   if(head->h_Glob.xsh_Flags & XPKSTREAMF_LONGHEADERS)
  547.   {
  548.     head->h_Loc.xch_Long.xchl_ULen = ulen;
  549.     head->h_Loc.xch_Long.xchl_CLen = clen;
  550.   }
  551.   else
  552.   {
  553.     head->h_Loc.xch_Word.xchw_ULen = (WORD) ulen;
  554.     head->h_Loc.xch_Word.xchw_CLen = (WORD) clen;
  555.   }
  556.  
  557.   if((rclen = clen&3))
  558.   {
  559.     clen -= rclen;
  560.     CopyMem(outbuf+clen, &end, rclen); /* copy the remaining bytes (max 3) */
  561.   }
  562.  
  563.   head->h_Loc.xch_Word.xchw_CChk = cchecksum((ULONG *) outbuf, clen >> 2)
  564.     ^ end[0] ^ end[1];
  565.   /* add the rest bytes to the checksum */
  566.   
  567.   head->h_Loc.xch_Word.xchw_HChk = 0;
  568.   head->h_Loc.xch_Word.xchw_HChk = hchecksum((STRPTR) &head->h_Loc, head->h_LocSize);
  569.  
  570.   if(!(MBUG hookwrite(xbuf, XIO_WRITE, &head->h_Loc, head->h_LocSize)))
  571.     return xbuf->xb_Result;
  572.  
  573.   if(!(MBUG hookwrite(xbuf, XIO_WRITE, outbuf, clen)))
  574.     return xbuf->xb_Result;
  575.  
  576.   if(rclen)
  577.   {
  578.     if(!(MBUG hookwrite(xbuf, XIO_WRITE, &end, 4)))
  579.       return xbuf->xb_Result;
  580.     clen += 4;
  581.   }
  582.  
  583.   head->h_Glob.xsh_ULen += ulen;
  584.   
  585.   xbuf->xb_Fib.xf_UCur += ulen;
  586.   xbuf->xb_Fib.xf_CCur += head->h_LocSize + clen;
  587.   xbuf->xb_Fib.xf_NLen = Min(max(xbuf->xb_InLen, head->h_Glob.xsh_ULen) -
  588.     xbuf->xb_Fib.xf_UCur, (LONG) xbuf->xb_ChunkSize);
  589.  
  590.   return xbuf->xb_Result;
  591. }
  592.  
  593. /**************************************************************************
  594.  *
  595.  *   XpkSeek() - move around on a compressed file
  596.  *
  597.  */
  598.  
  599. ASM(LONG) LIBXpkSeek(REG(a0, struct XpkBuffer *xbuf), REG(d0, LONG dist),
  600.     REG(d1, ULONG mode))
  601. {
  602.   xbuf->xb_Result = XPKERR_NOFUNC;
  603.   parsegettags(xbuf);
  604.  
  605.   return xbuf->xb_Result;
  606. }
  607.  
  608. /**************************************************************************
  609.  *
  610.  *   XpkClose() - finish (de)compressing an XPK file
  611.  *
  612.  */
  613.  
  614. ASM(LONG) LIBXpkClose(REG(a0, struct XpkBuffer *xbuf))
  615. {
  616.   struct Library *XpkSubBase = xbuf->xb_SubBase;
  617.  
  618.   if(!xbuf)
  619.     return 0;
  620.  
  621. #ifdef DEBUG
  622.   if(xbuf->xb_Result)
  623.     DebugError("XpkClose: failed (%ld) before XpkClose", xbuf->xb_Result);
  624. #endif
  625.  
  626.   if(xbuf->xb_Format == XPKMODE_PKSTD)
  627.   {
  628.     struct Headers *head = &xbuf->xb_Headers;
  629.     LONG outlen;
  630.  
  631.     if(!xbuf->xb_Result && !(xbuf->xb_Flags & XMF_GLOBHDR|XMF_NOPACK))
  632.     {
  633.       hookwrite(xbuf, XIO_WRITE, &head->h_Glob, sizeof(struct XpkStreamHeader));
  634. #ifdef DEBUG
  635.       if(xbuf->xb_Result) DebugError("XpkClose: failed to write globhdr");
  636. #endif
  637.       xbuf->xb_Fib.xf_CCur += sizeof(struct XpkStreamHeader);
  638.     }
  639.     if(!xbuf->xb_Result && !(xbuf->xb_Flags & XMF_NOPACK))
  640.     {
  641.       /******************* Write final chunk header *****************/
  642.       memset(&head->h_Loc, 0, head->h_LocSize);
  643.       head->h_Loc.xch_Word.xchw_Type = XPKCHUNK_END;
  644.       head->h_Loc.xch_Word.xchw_HChk = 0;
  645.       head->h_Loc.xch_Word.xchw_HChk =
  646.         hchecksum((STRPTR) &head->h_Loc, head->h_LocSize);
  647.  
  648.       hookwrite(xbuf, XIO_WRITE, &head->h_Loc, head->h_LocSize);
  649. #ifdef DEBUG
  650.       if(xbuf->xb_Result) DebugError("XpkClose: failed to write lochdr");
  651. #endif
  652.       xbuf->xb_Fib.xf_CCur += head->h_LocSize;
  653.       outlen = xbuf->xb_Fib.xf_CCur;
  654.  
  655.       /********************** Write global header *******************/
  656.       hookwrite(xbuf, XIO_SEEK, NULL, -outlen);
  657. #ifdef DEBUG
  658.       if(xbuf->xb_Result) DebugError("XpkClose: failed to reset output");
  659. #endif
  660.  
  661.       head->h_Glob.xsh_Pack = XPK_COOKIE;
  662.       head->h_Glob.xsh_CLen = outlen - 8;
  663.       head->h_Glob.xsh_HChk = 0;
  664.       head->h_Glob.xsh_HChk =
  665.         hchecksum((STRPTR) &head->h_Glob, sizeof(struct XpkStreamHeader));
  666.  
  667.       hookwrite(xbuf, XIO_WRITE, &head->h_Glob, sizeof(struct XpkStreamHeader));
  668. #ifdef DEBUG
  669.       if(xbuf->xb_Result) DebugError("XpkClose: failed updating globalhdr");
  670. #endif
  671.  
  672.       hookwrite(xbuf, XIO_SEEK, 0, outlen - sizeof(struct XpkStreamHeader));
  673. #ifdef DEBUG
  674.       if(xbuf->xb_Result) DebugError("XpkClose: failed to SEEK to end of output");
  675. #endif
  676.     }
  677.     xbuf->xb_Fib.xf_CLen = xbuf->xb_Fib.xf_CCur;
  678.     xbuf->xb_Fib.xf_ULen = xbuf->xb_Fib.xf_UCur;
  679.  
  680.     /*************************** Shut down *************************/
  681.     if(xbuf->xb_Flags & XMF_INITED)
  682.       XpksPackFree(&xbuf->xb_PackParam);
  683.   }
  684.   else if(xbuf->xb_Format == XPKMODE_UPSTD && xbuf->xb_Flags & XMF_INITED)
  685.     XpksUnpackFree(&xbuf->xb_PackParam);
  686.  
  687.   hookread(xbuf, xbuf->xb_Result ? XIO_ABORT : XIO_FREE, NULL, 0);
  688. #ifdef DEBUG
  689.   if(xbuf->xb_Result) DebugError("XpkClose: failed read ABORT/FREE");
  690. #endif
  691.  
  692.   hookwrite(xbuf, xbuf->xb_Result ? XIO_ABORT : XIO_FREE, NULL, 0);
  693. #ifdef DEBUG
  694.   if(xbuf->xb_Result) DebugError("XpkClose: failed write ABORT/FREE");
  695. #endif
  696.  
  697.   parsegettags(xbuf);        /* Send information to the user */
  698.  
  699. #ifdef DEBUG
  700.     DebugRunTime("XpkClose: InLen %ld, CLen %ld, ULen %ld, ID %.4s", xbuf->xb_InLen,
  701.     xbuf->xb_Fib.xf_CLen, xbuf->xb_Fib.xf_ULen, &xbuf->xb_Fib.xf_ID);
  702. #endif
  703.  
  704.   return freebufs(xbuf);
  705. }
  706.  
  707. #endif /* XPKMASTER_XPKMASTER_C */
  708.  
  709.